/*
 * ModelCC, distributed under ModelCC Shared Software License, www.modelcc.org
 */

package org.modelcc.language.syntax;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

/**
 * Context-free grammar rule.
 * 
 * @author Luis Quesada (lquesada@modelcc.org) & Fernando Berzal (fberzal@modelcc.org)
 */
public final class Rule implements Serializable 
{
    /**
     * User data.
     */
    private Object userData;

    /**
     * Left hand side element.
     */
    private RuleSymbol left;

    /**
     * Right hand side elements.
     */
    private List<RuleSymbol> right;

    /**
     * Builder.
     */
    private SymbolBuilder builder;

    /**
     * Post builder.
     */
    private SymbolBuilder postBuilder;

    /**
     * Default builder.
     */
    private static SymbolBuilder defaultBuilder = new SymbolBuilder() {

        @Override
        public boolean build(Symbol t, ParserMetadata data) {
            return true;
        }

    };

    
    /**
     * Constructor.
     */
    public Rule (RuleSymbol left) 
    {
    	this.left = left;
    	this.right = new ArrayList<RuleSymbol>();
    	this.builder = defaultBuilder;
    	this.postBuilder = defaultBuilder;
    	this.userData = null;
    }
    
    /**
     * Copy constructor
     * @param r Original rule
     */
    public Rule (Rule r)
    {
    	this.left = r.left;
    	this.right = new ArrayList<RuleSymbol>(r.right);
    	this.builder = r.builder;
    	this.postBuilder = r.postBuilder;
    	this.userData = r.userData;
    }

    // Getters & setters
    
    public RuleSymbol getLeft() 
    {
        return left;
    }

    public void setLeft(RuleSymbol left) 
    {
        this.left = left;
    }

    public List<RuleSymbol> getRight() 
    {
        return right;
    }

    public void add (RuleSymbol element)
    {
    	right.add(element);
    }
    
    public SymbolBuilder getBuilder() 
    {
        return builder;
    }

    public void setBuilder(SymbolBuilder builder) 
    {
        this.builder = builder;
        if (this.builder == null)
            this.builder = defaultBuilder;
    }

    public SymbolBuilder getPostBuilder() 
    {
        return postBuilder;
    }

    public void setPostBuilder(SymbolBuilder postBuilder) 
    {
        this.postBuilder = postBuilder;
        if (this.postBuilder == null)
            this.postBuilder = defaultBuilder;
    }

    
    public Object getUserData() 
    {
        return userData;
    }

    public void setUserData(Object userData) 
    {
        this.userData = userData;
    }

    
    // toString

    @Override
    public String toString() {
        String r = "";
        
        if (left!=null)
        	r += left.getType();
        else
        	r += "<null>";
        
        r += " ::= ";
        
        if (right!=null) {

        	for (int i=0; i<right.size();i++) {        		
        	    if (right.get(i)!=null)        	
        	    	r += right.get(i).getType()+" ";
        	    else
        	    	r+= "<null>";
        	}
        	    
        } else {
        	r += "<null>";
        }
        
        return r + " builder="+builder;
    }
    
}
